[Scala]02 Scala学习笔记

Scala模式匹配[最基础的模式匹配、加条件进行匹配、Array 模式匹配、List 模式匹配、类型匹配、异常处理、case class模式匹配、Some None模式匹配]、Scala函数高级操作[匿名函数与currying函数、高阶函数、偏函数]、隐式转换[隐式转换实战、隐式转换切面封装、隐式参数、隐式类]

Posted by 李玉坤 on 2018-03-16

Scala模式匹配

模式匹配
Java: 对一个值进行条件判断,返回针对不同的条件进行不同的处理

Scala:比java的功能强很多
变量 match {
case value1 => 代码1
case value2 => 代码2
…..
case _ => 代码N
}

最基础的模式匹配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import scala.util.Random

object MatchApp extends App {


val names = Array("Akiho Yoshizawa", "YuiHatano", "Aoi Sola")
val name = names(Random.nextInt(names.length))

name match {
case "Akiho Yoshizawa" => println("吉老师...")
case "YuiHatano" => println("波老师....")
case _ => println("真不知道你们在说什么....")
}

// def judgeGrade(grade:String): Unit = {
// grade match {
// case "A" => println("Excellent...")
// case "B" => println("Good...")
// case "C" => println("Just so so...")
// case _ => println("You need work harder...")
// }
// }
//
// judgeGrade("A")
// judgeGrade("C")
// judgeGrade("D")
}

加条件进行匹配

1
2
3
4
5
6
7
8
9
10
11
12
def judgeGrade(name:String, grade:String): Unit = {
grade match {
case "A" => println("Excellent...")
case "B" => println("Good...")
case "C" => println("Just so so...")
case _ if(name == "lisi") => println(name + ", you are a good boy, but...")
case _ => println("You need work harder...")
}
}

judgeGrade("zhangsan", "D")
judgeGrade("lisi", "D") // 双重过滤

Array 模式匹配

1
2
3
4
5
6
7
8
9
10
def greeting(array:Array[String]): Unit = {
array match {
case Array("zhangsan") => println("Hi:zhangsan")
case Array(x,y) => println("Hi:" + x + " , " + y)
case Array("zhangsan", _*) => println("Hi:zhangsan and other friends...")
case _ => println("Hi: everybody...")
}
}

greeting(Array("lisi","zhangsan","wangwu"))

List 模式匹配

1
2
3
4
5
6
7
8
9
10
def greeting(list:List[String]): Unit = {
list match {
case "zhangsan"::Nil => println("Hi:zhangsan")
case x::y::Nil => println("Hi:" + x + " , " + y)
case "zhangsan"::tail => println("Hi: zhangsan and other friends...")
case _ => println("Hi:everybody....")
}
}

greeting(List("zhangsan","lisi"))

类型匹配

1
2
3
4
5
6
7
8
9
10
def matchType(obj:Any): Unit = {
obj match {
case x:Int => println("Int")
case s:String => println("String")
case m:Map[_,_] => m.foreach(println)
case _ => println("other type")
}
}

matchType(Map("name"->"PK"))

异常处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
object ExceptionApp extends App {

//IO
val file = "test.txt"

try{

// open file
// use file

val i = 10/0
println(i)
} catch {
case e:ArithmeticException => println("除数不能为0..")
case e:Exception => println(e.getMessage)
} finally {

// 释放资源,一定要执行: close file

}

}

case class模式匹配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Person
case class CTO(name:String, floor:String) extends Person
case class Employee(name:String, floor:String) extends Person
case class Other(name:String) extends Person

def caseclassMatch(person:Person): Unit = {
person match {
case CTO(name,floor) => println("CTO name is: " + name + " , floor is: " + floor)
case Employee(name,floor) => println("Employee name is: " + name + " , floor is: " + floor)
case _ => println("other")
}
}

caseclassMatch(CTO("lisi", "22"))
caseclassMatch(Employee("zhangsan", "2"))
caseclassMatch(Other("other"))

Some None模式匹配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
  val grades = Map("lisi"->"A", "zhangsan"-> "C")

def getGrade(name:String): Unit = {
val grade = grades.get(name)

grade match {
case Some(grade) => println(name + ": your grade is :" + grade)
case None => println("Sorry....")
}
}

getGrade("zhangsan")
getGrade("lisi")
getGrade("wuangwu") //Sorry....

Scala函数高级操作

字符串高级操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
object StringApp extends App {


val s = "Hello:"
val name = "PK"
// println(s + name)

常用拼接写法
println(s"Hello:$name")
val team = "AC Milan"

// 插值
println(s"Hello:$name, Welcome to $team")

多行字符串,原样输出,几行就输出几行
val b =
"""
|这是一个多行字符串
|hello
|world
""".stripMargin //合成一行

println(b)
}

匿名函数与currying函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
* 匿名函数: 函数是可以命名的,也可以不命名
* (参数名:参数类型...) => 函数体
*/
object FunctionApp extends App {

匿名函数:
有名字:
// def sayHello(name:String): Unit = {
// println("Hi: " + name)
// }
//
// sayHello("PK")

无名字:
将匿名函数传递给变量
val m1 = (x:Int) => x+1
m1(10) //11

将匿名函数传递给函数
// def sum(a:Int, b:Int) = a+b
// println(sum(2,3))

currying函数:将原来接收两个参数一体的一个函数,转换成2个
// def sum2(a:Int)(b:Int) = a + b
// println(sum2(2)(3))

}

高阶函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

val l = List(1, 2, 3, 4, 5, 6, 7, 8)

//map函数: 逐个去操作集合中的每个元素
l.map((x: Int) => x + 1) 每个元素+1
l.map((x) => x * 2) 每个元素*2
l.map(x => x * 2) 一个参数可以省略括号,每个元素*2
l.map(_ * 2).foreach(println) 占位符 每个元素*2

//filter函数 过滤大于8的元素
l.map(_ * 2).filter(_ > 8).foreach(println)


//reduce 两两相邻的元素相加
l.reduce(_+_) // ((((((1+2)+3)+4)+5)+6)+7)+8

//reduceLeft
l.reduceLeft(_-_) // ((((((1-2)-3)-4)-5)-6)-7)-8

//reduceRight
l.reduceRight(_-_) // 1-(2-(3-(4-(5-(6-(7-8))))))

//fold
l.fold(0)(_-_) // (((((((0-1)-2)-3)-4)-5)-6)-7)-8

//fold
l.foldLeft(0)(_-_) // (((((((0-1)-2)-3)-4)-5)-6)-7)-8

//foldRight
l.foldRight(0)(_-_) // 1-(2-(3-(4-(5-(6-(7-(0-8)))))))

// l.max l.sum l.min

//flatten 元素合到一个list
scala> val f = List(List(1,2),List(3,4),List(5,6))
f: List[List[Int]] = List(List(1, 2), List(3, 4), List(5, 6))

scala> f.flatten
res18: List[Int] = List(1, 2, 3, 4, 5, 6)


// flatMap
scala> f.map(_.map(_*2))
res19: List[List[Int]] = List(List(2, 4), List(6, 8), List(10, 12))

scala> f.flatMap(_.map(_*2))
res20: List[Int] = List(2, 4, 6, 8, 10, 12)


[hadoop@hadoop ~]$ cat hello.txt
hello,hello,world

val txt = scala.io.Source.fromFile("/home/hadoop/hello.txt").mkString
// println(txt)
val txts = List(txt)
// 如何使用scala来完成wordcount统计
// 链式编程:Hibernate、Spark
txts.flatMap(_.split(",")).map(x => (x,1)) //...
.foreach(println)

偏函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import scala.util.Random

/**
* 偏函数:被包在花括号内没有match的一组case语句
*/
object PartitalFunctionApp extends App {

val names = Array("Akiho Yoshizawa", "YuiHatano", "Aoi Sola")
val name = names(Random.nextInt(names.length))

改造前:
name match {
case "Akiho Yoshizawa" => println("吉老师...")
case "YuiHatano" => println("波老师....")
case _ => println("真不知道你们在说什么....")
}

偏函数改造match PartialFunction修饰
// A 输入参数类型 B 输出参数类型
def sayChinese:PartialFunction[String,String] = {
case "Akiho Yoshizawa" => "吉老师..."
case "YuiHatano" => "波老师...."
case _ => "真不知道你们在说什么...."
}

println(sayChinese("Akiho Yoshizawa"))

}

隐式转换

隐式转换概述

需求:为一个已存在的类添加一个新的方法
Java:动态代理
Scala:隐式转换 双刃剑

隐式转换可以理解为:为一个已经存在的东西添加新小件

隐式转换实战

implicit def 方法名(普通的实例:普通的类):牛逼的类 = new 牛逼的类(普通的实例.参数名)

为Man类添加一个fly方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
object ImplicitApp {

// 定义隐式转换函数即可
implicit def man2superman(man:Man):Superman = new Superman(man.name)

val man = new Man("lisi")
man.fly()
}


class Man(val name: String) {
def eat(): Unit = {
println(s"man[ $name ] eat ..... ")
}
}

class Superman(val name: String) {
def fly(): Unit = {
println(s"superman[ $name ] fly ..... ")
}
}

File 增加一个read方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.io.File

object ImplicitApp {

implicit def file2RichFile(file: File): RichFile = new RichFile(file)

val file = new File("/home/hadoop/hello.txt")
val txt = file.read()
println(txt)

}

class RichFile(val file: File) {
def read() = {
scala.io.Source.fromFile(file.getPath).mkString
}
}

隐式转换切面封装

1
2
3
4
5
6
7
import java.io.File

object ImplicitAspect {
implicit def man2superman(man:Man):Superman = new Superman(man.name)

implicit def file2RichFile(file: File): RichFile = new RichFile(file)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import ImplicitAspect._  //导入隐式转换

object ImplicitApp {

// 或者可以针对导入,用到哪一个导入哪一个 import ImplicitAspect.man2superman

val man = new Man("lisi")
man.fly()
}


class Man(val name: String) {
def eat(): Unit = {
println(s"man[ $name ] eat ..... ")
}
}

class Superman(val name: String) {
def fly(): Unit = {
println(s"superman[ $name ] fly ..... ")
}
}

隐式参数

指的是在函数或者方法中,定义一个用implicit修饰的参数,此时Scala会尝试找到一个指定类型的,用implicit修饰的对象,即隐式值,并注入参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.io.File

object ImplicitApp {

//implicit val name = "test" 放到伴生对象领域里也可以访问到

def main(args: Array[String]): Unit = {
def testParam(implicit name:String): Unit = {
println(name + "~~~~~~~~~~~~")
}

第一种调用方式
testParam("zhangsan")

第二种调用方式
implicit val name = "test"
testParam
}

下列会报错,因为丢进去了两个 implicit
implicit val s1 = "s1"
implicit val s2 = "s2"
testParam

}

隐式类

1
2
3
4
5
6
7
8
9
10
object ImplicitClassApp extends App {

// Calculator 隐式类 代表了所有的Int类型都有了add方法
implicit class Calculator(x:Int) {
def add(a:Int) = a + x
}

println(12.add(3))

}